<?php
/**
 * Created by PhpStorm.
 * User: nightelf
 * Date: 2020/1/19
 * Time: 16:22
 */

namespace App\Http\Model;


use App\Exceptions\ApiException;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class WarehouseModel
{
    const TABLE = 'warehouse';

    /**
     * @param array $data
     * @return mixed
     */
    public function lists(array $data)
    {
        $result = DB::table(self::TABLE)
            ->leftJoin('material as m', 'm.id', '=', self::TABLE . '.materialId')
            ->leftJoin('material_spec as ms', 'ms.id', '=', self::TABLE . '.specId')
            ->leftJoin('unit as u', 'u.id', '=', self::TABLE . '.unitId')
            ->where(function ($query) use ($data) {
                if (isset($data['projectId']) && !is_null($data['projectId'])) {
                    $query->where(self::TABLE . '.projectId', $data['projectId']);
                }
                if (!empty($data['type'])) {
                    $query->where('m.categoryId', $data['type']);
                }
                if (!empty($data['buyType'])) {
                    $query->where(self::TABLE . '.buyType', $data['buyType']);
                }
                if (isset($data['search']) && !is_null($data['search'])) {
                    $query->where('m.name', 'like', '%' . $data['search'] . '%');
                }
            });
        if (!empty($data['length']) && !empty($data['page'])) {
            $limit = config('yucheng.limit');
            $start = 0;
            if (!empty($data['length'])) {
                $limit = $data['length'];
            }
            if (!empty($data['page'])) {
                $start = ($data['page'] - 1) * $limit;
            }
            $result = $result->offset($start)->limit($limit);
        }

        return $result->select(self::TABLE . '.*', 'm.name as materialName', 'ms.spec', 'u.name as unitName')
            ->get()->toArray();
    }

    /**
     * @param array $data
     * @return mixed
     */
    public function countLists(array $data)
    {
        return DB::table(self::TABLE)
            ->leftJoin('material as m', 'm.id', '=', self::TABLE . '.materialId')
            ->leftJoin('material_spec as ms', 'ms.id', '=', self::TABLE . '.specId')
            ->leftJoin('unit as u', 'u.id', '=', self::TABLE . '.unitId')
            ->where(function ($query) use ($data) {
                if (isset($data['projectId']) && !is_null($data['projectId'])) {
                    $query->where(self::TABLE . '.projectId', $data['projectId']);
                }
                if (!empty($data['type'])) {
                    $query->where('m.categoryId', $data['type']);
                }
                if (!empty($data['buyType'])) {
                    $query->where(self::TABLE . '.buyType', $data['buyType']);
                }
                if (isset($data['search']) && !is_null($data['search'])) {
                    $query->where('m.name', 'like', '%' . $data['search'] . '%');
                }
            })
            ->count();
    }

    /**
     * @param array $data
     * @return array
     */
    public function info(array $data)
    {
        $result = DB::table(self::TABLE)
            ->leftJoin('material as m', 'm.id', '=', self::TABLE . '.materialId')
            ->where(function ($query) use ($data) {
                foreach ($data as $k => $d) {
                    $query->where(self::TABLE . '.' . $k, $d);
                }
            })
            ->select(self::TABLE . '.*', 'm.name as materialName')
            ->first();
        return empty($result) ? [] : get_object_vars($result);
    }

    /**
     * @param array $where
     * @param array $data
     * @return mixed
     */
    public function update(array $where, array $data)
    {
        return DB::table(self::TABLE)->where($where)->update($data);
    }

    /**
     * @param array $data
     * @return mixed
     */
    public function insert(array $data)
    {
        return DB::table(self::TABLE)->insert($data);
    }

    /**
     * @param array $data
     * @return bool
     */
    public function receipt(array $data)
    {

    }

    /**
     * @param array $data
     * @return
     * @throws ApiException
     */
    public function expend(array $data)
    {
        try {
            return DB::transaction(function () use ($data) {
                $warehouseModel = new WarehouseModel();
                //扣除库存
                foreach ($data['data'] as $key => $d) {
                    $warehouseInfo = $warehouseModel->info([
                        'id' => $d['id'],
                    ]);
                    $newAmount = $warehouseInfo['amount'] - $d['amount'];
                    $data['data'][$key]['purchasePrice'] = $warehouseInfo['purchasePrice'];
                    $data['data'][$key]['salePrice'] = $warehouseInfo['salePrice'];
                    $warehouseModel->update(['id' => $warehouseInfo['id']], ['amount' => $newAmount, 'updateTime' => date('Y-m-d H:i:s')]);
                    $logData = [
                        'materialId' => $warehouseInfo['materialId'],
                        'specId' => $warehouseInfo['specId'],
                        'amount' => $d['amount'],
                        'price' => $warehouseInfo['purchasePrice'],
                        'totalPrice' => $d['amount'] * $warehouseInfo['purchasePrice'],
                        'unitId' => $d['unitId'],
                        'surplus' => $newAmount,
                    ];
                    $data['data'][$key] = $logData;
                }
                (new WarehouseLogModel)->addLog($data);
            });
        } catch (\Exception $e) {
            throw new ApiException('[' . $e->getLine() . '][' . $e->getFile() . ']' . $e->getMessage(), 460506);
//            throw new ApiException('减库存过程失败', 460705);
        }
    }

    /**
     * @param array $data
     * @return bool
     * @throws ApiException
     */
    public function ex_warehouse(array $data)
    {
        DB::beginTransaction();
        try {
                $warehouseModel = new WarehouseModel();
                //扣除库存
                $totalPrice = 0;
                foreach ($data['data'] as $key => $d) {
                    $warehouseInfo = $warehouseModel->info(['projectId'=>$data['projectId'],'materialId'=>$d['materialId'],'specId'=>$d['specId']]);
                    $newAmount = $warehouseInfo['amount'] - $d['amount'];
                    $data['data'][$key]['purchasePrice'] = $warehouseInfo['purchasePrice'];
                    $data['data'][$key]['salePrice'] = $warehouseInfo['salePrice'];
                    $warehouseModel->update(['id' => $warehouseInfo['id']], ['amount' => $newAmount, 'updateTime' => date('Y-m-d H:i:s')]);
                    $logData = [
                        'materialId' => $warehouseInfo['materialId'],
                        'specId' => $warehouseInfo['specId'],
                        'supplierId' => empty($warehouseInfo['supplierId'])?0:$warehouseInfo['supplierId'],
                        'amount' => $d['amount'],
                        'price' => $warehouseInfo['salePrice'],
                        'totalPrice' => $d['amount'] * $warehouseInfo['salePrice'],
                        'unitId' => $d['unitId'],
                        'surplus' => $newAmount,
                    ];
                    $totalPrice += $d['amount'] * $warehouseInfo['salePrice'];
                    $data['data'][$key] = $logData;
                }
                $data['price'] = $totalPrice;
                (new WarehouseLogModel)->addLog($data);
            DB::commit();
            return true;
        } catch (\Exception $e) {
            Log::info($e->getMessage() . ' in ' . $e->getFile() . '(' . $e->getLine() . ')');
            DB::rollback();
            return false;
        }
    }

    public function materialLists(array $where)
    {
        return DB::table(self::TABLE)
            ->leftJoin('material as m', 'm.id', '=', self::TABLE . '.materialId')
            ->where($where)
            ->groupBy(self::TABLE.'.materialId')
            ->select(self::TABLE . '.*', 'm.name as materialName')
            ->get()->toArray();
    }

    public function specLists(array $data)
    {
        return DB::table(self::TABLE)
            ->leftJoin('material_spec as ms', 'ms.id', '=', self::TABLE . '.specId')
            ->leftJoin('unit as u', 'u.id', '=', self::TABLE . '.unitId')
            ->where(function($query) use($data){
                $query->where(self::TABLE . '.projectId', $data['projectId'])
                    ->where(self::TABLE . '.materialId', $data['materialId']);
            })
            ->groupBy(self::TABLE.'.specId')
            ->select(self::TABLE . '.*', 'ms.spec', 'u.name as unitName')
            ->get()->toArray();
    }

    /**
     * 此方法没用了
     * @param array $data
     * @return bool
     */
    public function adjust(array $data)
    {
        DB::beginTransaction();
        try {
            $warehouseModel = new WarehouseModel();
            $warehouseLogModel = new WarehouseLogModel();
            $warehouseLogInfoModel = new WarehouseLogInfoModel();
            //调拨前的仓库出库记录
            $logId = $warehouseLogModel->insert([
                'projectId' => $data['projectId'],
                'price' =>0,
                'type' => $warehouseLogModel::ALLOT,
                'sourceProjectId' => $data['newProjectId'],
                'time' => $data['time'],
                'createTime' => date('Y-m-d H:i:s'),
                'remark' => $data['remark'],
                'adminId' =>$data['adminId'],
            ]);

            $newLogId = $warehouseLogModel->insert([
                'projectId' => $data['newProjectId'],
                'price' =>0,
                'type' => $warehouseLogModel::RECEIPT,
                'sourceProjectId' => $data['projectId'],
                'time' => $data['time'],
                'createTime' => date('Y-m-d H:i:s'),
                'remark' => $data['remark'],
                'adminId' =>$data['adminId'],
            ]);
            foreach ($data['data'] as $key => $d) {
                //更新原仓库库存
                $info = $warehouseModel->info(['projectId'=>$data['projectId'],'materialId'=>$d['materialId'],'specId'=>$d['specId']]);
                $amount = $info['amount']-$d['amount'];
                $warehouseModel->update(['id'=>$info['id']],['amount'=>$amount]);
                //更新原项目出入库记录
                $warehouseLogInfoModel->insert([
                    'logId'=>$logId,
                    'materialId' => $d['materialId'],
                    'specId' => $d['specId'],
                    'amount' => $d['amount'],
                    'surplus' =>$amount,
                    'price' => $info['purchasePrice'],
                    'totalPrice' => $d['amount']*$info['purchasePrice'],
                    'unitId' => $d['unitId'],
                ]);
                //更新新仓库库存
                $newInfo = $warehouseModel->info(['projectId'=>$data['newProjectId'],'materialId'=>$d['materialId'],'specId'=>$d['specId']]);
                if(empty($newInfo)){
                    $warehouseModel->insert([
                        'projectId' =>$data['newProjectId'],
                        'materialId' => $d['materialId'],
                        'specId' => $d['specId'],
                        'amount' => $d['amount'],
                        'unitId' => $info['unitId'],
                        'purchasePrice' => $info['purchasePrice'],
                        'updateTime' => date('Y-m-d H:i:s'),
                    ]);
                    $newAmount = $d['amount'];
                }else{
                    $newAmount = $newInfo['amount']+$d['amount'];
                    $newPurchasePrice = ($d['amount']*$info['purchasePrice']+$newInfo['amount']*$newInfo['purchasePrice'])/$newAmount;
                    $warehouseModel->update(['id'=>$newInfo['id']],['amount'=>$newAmount,'purchasePrice'=>$newPurchasePrice]);
                }
                $warehouseLogInfoModel->insert([
                    'logId'=>$newLogId,
                    'materialId' => $d['materialId'],
                    'specId' => $d['specId'],
                    'amount' => $d['amount'],
                    'surplus' =>$newAmount,
                    'price' => $info['purchasePrice'],
                    'totalPrice' => $d['amount']*$info['purchasePrice'],
                    'unitId' => $d['unitId'],
                ]);
            }

            DB::commit();
            return true;
        } catch (\Exception $e) {
            Log::info($e->getMessage() . ' in ' . $e->getFile() . '(' . $e->getLine() . ')');
            DB::rollback();
            return false;
        }
    }
}